package br.pucrio.inf.tamdera.measurement;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;

import br.pucrio.inf.tamdera.TamderaException;

public class TogetherCsvMetricsCollector  {

	private Hashtable<String, Hashtable<String, Double>> cache;
	private ArrayList<String> metricsNames;

	public TogetherCsvMetricsCollector() 
	{
		this.cache = new Hashtable<String, Hashtable<String, Double>>();
		this.metricsNames = new ArrayList<String>();
	}

	public TogetherCsvMetricsCollector(String csvFilePath) {
		this();
		this.loadMetricsFromFileIntoCache(csvFilePath);
	}

	private void loadMetricsFromFileIntoCache(String csvFilePath) {
		try {
			BufferedReader csvFile = new BufferedReader(new FileReader(
					csvFilePath));

			this.parseMetrics(csvFile);
			
			csvFile.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			TamderaException except = new TamderaException("The system was not able to open and parser the metric file");
			throw except; 
		} catch (IOException e) {
			e.printStackTrace();
			TamderaException except = new TamderaException("The system was not able to open and parser the metric file");
			throw except;
		}
	}

	private void parseMetrics(BufferedReader csvInput) throws IOException {
		String header = csvInput.readLine();

		if (header != null) {
			loadMetricsNames(header);
			loadMetricsValues(csvInput);
		}
	}

	private void loadMetricsValues(BufferedReader csvInput) throws IOException {

		String row = csvInput.readLine();

		while (row != null) {
			String[] dataArray = row.split(",");
			this.cache.put(dataArray[0], new Hashtable<String, Double>());
			loadMetricsRow(dataArray);
			
			row = csvInput.readLine();
		}
	}

	private void loadMetricsRow(String[] metrics) {
		String resource = metrics[0];
		for (int i = 1; i < metrics.length; i++) {
			String token = metrics[i];

			if (token == null || token.length() == 0)
				continue;

			this.cache.get(resource).put(metricsNames.get(i - 1),
					Double.parseDouble(token));
		}
	}

	private void loadMetricsNames(String header) {
		String[] dataArray = header.split(",");
		// first line is the header; load metrics names
		for (int i = 1; i < dataArray.length; i++) {
			metricsNames.add(dataArray[i]);
		}
	}

	private void print() {
		Enumeration<String> itens = this.cache.keys();
		while(itens.hasMoreElements()) {
			String next = itens.nextElement();
			System.out.println(next + ": ");
			System.out.println(this.cache.get(next).size() + " metrics");
			System.out.println(this.cache.get(next).toString());
		}
	}

	public static void main(String[] args) {
		TogetherCsvMetricsCollector collector = new TogetherCsvMetricsCollector();
		String metrics = "Resource,A,AC,AHF,AID,AIF,AIUR,ALD,AOFD,AUF,CA,CBO,CC,CE,CF,CIW,CL,CM,COC,CR,ChC,DAC,DD,DOIH,EC,FO,HDiff,HEff,HPLen,HPVoc,HPVol,I,IUR,JUC,LCOM1,LCOM2,LCOM3,LOC,MDC,MHF,MIC,MIF,MNOB,MNOL,MNOP,MPC,MSOO,NAM,NCC,NIC,NOA,NOAM,NOC,NOCC,NOCON,NOCP,NOED,NOIS,NOLV,NOM,NOO,NOOM,NOP,NOPA,NORM,NOprnd,NOprtr,NUOprnd,NUOprtr,PC,PF,PIS,PPkgM,PPrivM,PProtM,PPubM,PS,PUR,RFC,RMD,TCC,TCR,TRAp,TRAu,TRDp,TRDu,VOD,WCM,WMPC1,WMPC2,WOC"
				+ "\nbr.pucrio.inf.les.genius,,14,37,,18,,,,,,27,6,,25,,,,,0,,2,,4,13,16,216,202713,2261,89,12226,,,0,62,100,87,875,18,13,40,83,,4,5,,6,,,,10,2,26,3,2,,,17,,16,12,4,,,35,994,1267,73,19,,33,,13,22,2,63,,,111,,,0,3,40,2,6,16,,27,19,"
				+ "\nbr.pucrio.inf.les.genius.br.pucrio.inf.les.genius.archdesign,0,17,,,,,,,,1,2,1,2,,,,,,0,,1,,1,6,1,4,119,26,8,74,67,,0,6,73,66,40,6,,0,,,0,2,,1,,1,,3,,2,0,2,1,2,2,,7,4,0,,,0,16,10,6,2,200,,2,32,0,0,69,2,100,15,24,,0,0,0,0,0,0,,6,6,";

		StringReader reader = new StringReader(metrics);
		BufferedReader buffered = new BufferedReader(reader);
		try {
			collector.parseMetrics(buffered);
			collector.print();
			
			//asserting
			System.out.println(collector.cache.get("br.pucrio.inf.les.genius").get("LOC"));
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public Hashtable<String, Hashtable<String, Double>> getCache() {
		return cache;
	}

	public void setCache(Hashtable<String, Hashtable<String, Double>> cache) {
		this.cache = cache;
	}

	public ArrayList<String> getMetricsNames() {
		return metricsNames;
	}

	public void setMetricsNames(ArrayList<String> metricsNames) {
		this.metricsNames = metricsNames;
	}

}
